-
Notifications
You must be signed in to change notification settings - Fork 3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Initial support for ARM64 Windows #8142
Conversation
CT Test Results 10 files 248 suites 3h 28m 48s ⏱️ For more details on these failures, see this check. Results for commit 88a1244. ♻️ This comment has been updated with latest results. To speed up review, make sure that you have read Contributing to Erlang/OTP and that all checks pass. See the TESTING and DEVELOPMENT HowTo guides for details about how to run test locally. Artifacts
// Erlang/OTP Github Action Bot |
1b08767
to
73bc87e
Compare
Hi, I have also managed to craft a GitHub workflow that can build it natively on an ARM64 Windows machine, and here is the workflow log, the corresponding CI yaml file and the final installer! This build was based on 6c6b409. There're still some issues when cross-compiling on x86_64 machine, which I'll look into later. Other than that, all libraries except wx and odbc build without any issue, ARM64 JIT also seem to work. Although I haven't got time to do any thorough tests yet. And one more thing is to adjust nsis scripts where relevant, such as defaulting to |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the PR! I've got a few questions in the comments below :)
b590118
to
becdd6d
Compare
becdd6d
to
08bebe0
Compare
08bebe0
to
0dc9a4c
Compare
updated installation guide build with native-ethr-impls enable updated installation guide
arm64 jit now works on windows
fix cross-compile on x86_64 for aarch64
And I was wondering if and which ones of these failed test cases should we address in this PR? Perhaps the ones in the |
The hard crashes must be fixed before we can include this in the nightly test runs, and the rest need to be investigated and fixed before we merge it. :-) |
I found that a few of these hard-crashed ones were related to #ifdef __WIN32__
printf("[debug] we're in display_string_2 win32\r\n");
HANDLE fd;
if (ERTS_IS_ATOM_STR("stdout", BIF_ARG_1)) {
fd = GetStdHandle(STD_OUTPUT_HANDLE);
printf("[debug] and the BIF_ARG_1 is stdout, fd=%d\r\n", fd);
} else if (ERTS_IS_ATOM_STR("stderr", BIF_ARG_1)) {
fd = GetStdHandle(STD_ERROR_HANDLE);
printf("[debug] and the BIF_ARG_1 is stderr, fd=%d\r\n", fd);
if (fd == INVALID_HANDLE_VALUE) {
printf("[debug] and fd == INVALID_HANDLE_VALUE\r\n");
}
}
#else
// ...
#endif
#ifdef __WIN32__
Uint32 w;
if (!WriteFile(fd, str, len, &w, NULL)) {
DWORD last_error = GetLastError();
LPTSTR error_text = NULL;
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, HRESULT_FROM_WIN32(last_error), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&error_text, 0, NULL);
if (error_text != NULL) {
printf("[debug] error msg: %s\r\n", error_text);
LocalFree(error_text);
} else {
printf("[debug] error msg: cannot get formatted error message\r\n");
}
goto error;
}
written = (Sint)w;
#else
// ...
#endif The coresponding test case was changed to: display_string(Config) when is_list(Config) ->
# using `erlang:display` for comparison and check that we can display to console
true = erlang:display("hej"),
true = erlang:display_string("hej"),
ok. And I got this output when running this test case:
And I also attempted to use #ifdef __WIN32__
int fd;
if (ERTS_IS_ATOM_STR("stdout", BIF_ARG_1)) {
fd = _fileno(stdout);
} else if (ERTS_IS_ATOM_STR("stderr", BIF_ARG_1)) {
fd = _fileno(stderr);
}
#else
// ...
#endif
#ifdef __WIN32__
written = 0;
do {
res = _write(fd, str+written, len-written);
if (res < 0 && errno != ERRNO_BLOCK && errno != EINTR) {
printf("[debug] _write went wrong, errno=%d\r\n", errno);
goto error;
}
written += res;
} while (written < len);
#else
// ...
#endif The test outputted:
Yet this function seems to be fine when using
I wonder if we should skip this test for ARM64 Windows or using some alternatives? |
And for this particular function, if [ X"$X64" = X"true" ]; then
echo_setenv OVERRIDE_TARGET win32 ';'
echo_setenv CONFIG_SUBTYPE win64 ';'
elif [ X"$ARM64" = X"arm64" -o X"$ARM64" = X"x64_arm64" ]; then
echo_setenv OVERRIDE_TARGET aarch64-pc-windows ';'
echo_setenv CONFIG_SUBTYPE "$ARM64" ';'
else
echo_setenv OVERRIDE_TARGET win32 ';'
fi |
Isn't win32 used as the name of the used API and we still use that on arm for windows? |
Oh it's probably just a minor thing. I was trying to find a way to detect the CPU architecture using erlang:system_info(system_architecture). For other systems, the result can usually be used to check the CPU architecture, for example, os:getenv("PROCESSOR_ARCHITECTURE"). Besides that, it also doesn't follow the official document:
Maybe it's too late and would definitely break a lot of things for x86 and x86_64 Windows, but perhaps we can do it for ARM64 Windows. WDYT? |
I still can't figure out why Windows think the file handle we get from emulator
kernel
I'll upload a screenshot for the |
Some explanation for commit 892019a During my tests, I found that erts_time_sup__.r.o.start_offset.nsec = (ErtsMonotonicTime)
erts_time_unit_conversion((Uint64) abs_native_offset,
(Uint32) ERTS_MONOTONIC_TIME_UNIT,
(Uint32) 1000*1000*1000); The value of #include <stdio.h>
#include <stdint.h>
uint64_t
erts_time_unit_conversion(uint64_t value,
uint32_t from_time_unit,
uint32_t to_time_unit)
{
uint64_t high, low, result;
if (value <= ~((uint64_t) 0)/to_time_unit)
return (value*to_time_unit)/from_time_unit;
low = value & ((uint64_t) 0xffffffff);
high = (value >> 32) & ((uint64_t) 0xffffffff);
low *= to_time_unit;
high *= to_time_unit;
high += (low >> 32) & ((uint64_t) 0xffffffff);
low &= ((uint64_t) 0xffffffff);
result = high % from_time_unit;
high /= from_time_unit;
printf("[!] high=%llu\n", high);
printf("[!] high will overflow=%s\n", (high >> 32) != 0 ? "yes" : "no");
high <<= 32;
printf("[!] high=%llu, result=%llu\n", high, result);
result <<= 32;
result += low;
result /= from_time_unit;
result += high;
return result;
}
int main(int argc, char *argv[]) {
printf("%lld\n\n", erts_time_unit_conversion(576460752312000000, 24000000, 1000*1000*1000));
printf("%lld\n", erts_time_unit_conversion(576460752312000000, 24000000, 1000*1000));
} The output of the above minimal code is
The correct value of the final result should be And this overflow will cause all subsequent calculations depending on As for the fix, I think one possible (and perhaps the easiest and the most striaghtforwad) way is that we can simply do the calculations in erlang code. I tried to detect if there's any overflow in the C code and if so, we handle it in erlang code. But after I've done that, I feel that it just adds some unnecessary complexity to the C code. I hope all this would make sense, but I'm happy to make any other changes to the C code if there's a better solution for it. |
I was wondering if I should try to use |
Hi all! As this is kinda stale, I wonder if it would be easier for us if I break this PR into smaller PRs? I can start with PRs that definitely won't break any existing things. |
I'm closing this one, since you have started with smaller PR's. |
Hi, this PR includes initial patches and instructions to bring Erlang/OTP to ARM64 Windows. These changes should only affect the behaviour when running in WSL and user executes one of the following command to set up the build environment
./otp_build env_win32 arm64
, set up build environment for compiling ARM64 Erlang/OTP natively,./otp_build env_win32 x64_arm64
, set up build environment for cross-compiling ARM64 Erlang/OTP on an x86_64 machineAlthough I understand that ARM64 Windows might not be anywhere close to the main tier of support yet, this PR can serve as an initial guide for people in the community who're also interested in running Erlang/OTP natively on ARM64 Windows.